home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / examples / demo / demosrc / d_globe.pro < prev    next >
Text File  |  1997-07-08  |  29KB  |  837 lines

  1. ; $Id: d_globe.pro,v 1.19 1997/04/18 17:51:14 alan Exp $
  2. ;
  3. ;  Copyright (c) 1997, Research Systems, Inc. All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5. ;
  6. ;+
  7. ;  FILE:
  8. ;       d_globe.pro
  9. ;
  10. ;  CALLING SEQUENCE: d_globe
  11. ;
  12. ;  PURPOSE:
  13. ;       Demonstrates texture mapping, model rotations, and indexed color
  14. ;       table stretching with IDL's object graphics system.
  15. ;       (object graphics only)
  16. ;
  17. ;  MAJOR TOPICS: Indexed colors & Color palettes, Texture Mapping, Trackball.
  18. ;
  19. ;  CATEGORY:
  20. ;       IDL 5.0
  21. ;
  22. ;  INTERNAL FUNCTIONS and PROCEDURES:
  23. ;       pro globergbstretch       - stretches RGB vectors into new RGB vectors
  24. ;       pro globestretch_event   - event handler for stretching colors
  25. ;       pro d_globe_event           - event handler
  26. ;       pro d_globecleanup          - cleanup routine
  27. ;       pro globereadimages       - inputs and scales images
  28. ;       function globemakeobjects - creates the object hierarchy
  29. ;       pro d_globe                 - Main procedure
  30. ;
  31. ;  EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
  32. ;       pro trackball__define.pro - Create trackball object.
  33. ;       pro orb__define.pro  - Create an orb object
  34. ;       pro gettips               - Get the tips text structure..
  35. ;       pro widtips               - Create the widget text for tips.
  36. ;       globe.txt                 - "About" file
  37. ;       globe.tip                 - "Tips" file
  38. ;       worldelv.dat              - global topography image dataset
  39. ;       worldtmp.sav              - global temperature image dataset & RGB's
  40. ;
  41. ;  REFERENCE: IDL Reference Guide, IDL User's Guide
  42. ;
  43. ;
  44. ;  NAMED STRUCTURES:
  45. ;       none.
  46. ;
  47. ;  COMMON BLOCS:
  48. ;       none.
  49. ;
  50. ;  MODIFICATION HISTORY: Written by:  MCR, RSI,  February 97
  51. ;-
  52. ;----------------------------------------------------------------------
  53. ; PURPOSE  This routine stretches old RGB vectors
  54. ;          (oldReds, oldGreens, oldBlues)  based on
  55. ;          low and high stretch values (low, high)
  56. ;          and passes back new  RGB vectors
  57. ;          (newReds, newGreens, newBlues).  This routine 
  58. ;          is based on the Stretch.pro routine found within
  59. ;          the IDL distribution.  One  may stretch color vectors
  60. ;          of any length.
  61. ;
  62. pro GlobeRGBStretch, $
  63.     oldReds, oldGreens, oldBlues, $    ;IN: Input RGB Vectors
  64.     newReds, newGreens, newBlues, $    ;OUT: Output RGB Vectors
  65.     LOW=low, HIGH=high            ;IN: (opt) stretch indices
  66.  
  67.     WIDGET_CONTROL, HOURGLASS = 1
  68.  
  69.     nColors=N_ELEMENTS(oldReds)
  70.  
  71.     if (not KEYWORD_SET(low)) then $
  72.         low=0L
  73.  
  74.     if (not KEYWORD_SET(high)) then $
  75.         high=nColors-1L
  76.  
  77.     if (high-low ne 0) then begin        ;if low and high are not equal
  78.         slope=FLOAT(nColors-1)/(high-low)
  79.         intercept=-slope*low
  80.     endif else begin                     ;if low and high are equal
  81.         slope=0b & intercept=low
  82.     endelse
  83.  
  84.     sub=LONG(FINDGEN(nColors)*slope+intercept)
  85.     newReds=oldReds[sub]
  86.     newGreens=oldGreens[sub]
  87.     newBlues=oldBlues[sub]
  88.     WIDGET_CONTROL, HOURGLASS = 0
  89.  
  90. end
  91.  
  92. ;----------------------------------------------------------------------
  93. ;
  94. ; PURPOSE ; This is a secondary event handler routine
  95. ;           used in the Globe demo. This routine is used
  96. ;           to stretch the coor indices of the respective
  97. ;           datasets. One can either stretch the color vectors
  98. ;           for the temperature data or stretch the colors
  99. ;           vectors for the topography data.
  100. ;
  101. pro GlobeStretch_Event, $
  102.     sEvent
  103.  
  104.     WIDGET_CONTROL, HOURGLASS = 1
  105.     WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  106.     WIDGET_CONTROL, sEvent.id, GET_UVALUE=wsliders
  107.  
  108.     ;  Build subscripts of RGB vectors associated
  109.     ;  with the images.
  110.     ;
  111.     elev=LINDGEN(sState.nColors/2)
  112.     temps=LINDGEN(sState.nColors/2)+sState.nColors/2
  113.  
  114.     ;  Check that minimim sliders do not exceed
  115.     ;  the maximum sliders and
  116.     ;  that maximum sliders are not less than minimum sliders
  117.     ;  and make adjustments as needed.
  118.     ;
  119.     WIDGET_CONTROL, wsliders[0], GET_VALUE=sliderValue0
  120.     WIDGET_CONTROL, wsliders[1], GET_VALUE=sliderValue1
  121.     WIDGET_CONTROL, wsliders[2], GET_VALUE=sliderValue2
  122.     WIDGET_CONTROL, wsliders[3], GET_VALUE=sliderValue3
  123.  
  124.     if (sEvent.id EQ wsliders[0] and sliderValue0 gt sliderValue1) then begin
  125.         WIDGET_CONTROL, wsliders[0], SET_VALUE=sliderValue1
  126.         sliderValue0 = sliderValue1
  127.     endif
  128.  
  129.     if (sEvent.id EQ wsliders[1] and sliderValue0 gt sliderValue1) then begin
  130.         WIDGET_CONTROL, wsliders[1], SET_VALUE=sliderValue0
  131.         slidervalue1 = sliderValue0
  132.     endif
  133.  
  134.     if (sEvent.id EQ wsliders[2] and sliderValue2 gt sliderValue3) then begin
  135.         WIDGET_CONTROL, wsliders[2], SET_VALUE=sliderValue3
  136.         sliderValue2 = sliderValue3
  137.     endif
  138.  
  139.     if (sEvent.id EQ wsliders[3] and sliderValue2 gt sliderValue3) then begin
  140.         WIDGET_CONTROL, wsliders[3], SET_VALUE=sliderValue2
  141.         sliderValue3 = sliderValue2
  142.     endif
  143.  
  144.     ;  Stretch the original color vectors and then save the stretched
  145.     ;  vectors into the color palette.  Note, the original colors are
  146.     ;  always stretch so that information is not lost by stretching
  147.     ;  vectors that have already been stretched.
  148.     ;  (both datasets individually)
  149.     ;
  150.     GlobeRGBStretch, sState.reds[elev], sState.greens[elev], $
  151.         sState.blues[elev], newReds1, newGreens1, newBlues1, $
  152.         LOW=sliderValue0, HIGH=sliderValue1
  153.  
  154.     GlobeRGBStretch, sState.reds[temps], sState.greens[temps], $
  155.         sState.blues[temps], newReds2, newGreens2, newBlues2, $
  156.         LOW=sliderValue2-sState.ncolors/2, $
  157.         HIGH=sliderValue3-sState.ncolors/2
  158.  
  159.     reds=[newReds1, newReds2]
  160.     greens=[newGreens1, newGreens2]
  161.     blues=[newBlues1, newBlues2]
  162.  
  163.     sState.oPalette->SetProperty, RED_VALUES=reds, $
  164.         GREEN_VALUES=greens, BLUE_VALUES=blues
  165.  
  166.     sState.oWindow->Draw, sState.oView
  167.  
  168.     WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  169.     WIDGET_CONTROL, HOURGLASS = 0
  170.  
  171. end
  172.  
  173. ;----------------------------------------------------------------------
  174. ;
  175. ; PURPOSE  This is the main event handler routine
  176. ;          use in the Globe demo.
  177. ;
  178. pro d_Globe_Event, $
  179.     sEvent
  180.  
  181.     ;  Quit this application using the close box.
  182.     ;
  183.     if (TAG_NAMES(sEvent, /STRUCTURE_NAME) EQ $
  184.         'WIDGET_KILL_REQUEST') then begin
  185.         WIDGET_CONTROL, sEvent.top, /DESTROY
  186.         RETURN
  187.     endif
  188.  
  189.     WIDGET_CONTROL, sEvent.id, GET_UVALUE=uvalue
  190.     case uvalue of
  191.  
  192.         ;  Handle radio button events .
  193.         ;  Here Handle event for showing over continents.
  194.         ;
  195.         'RADIO1': begin
  196.             WIDGET_CONTROL, HOURGLASS=1
  197.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  198.             WIDGET_CONTROL, sState.wGroup2, GET_VALUE=twin
  199.             if (sEvent.value EQ 0 AND twin EQ 0) then $
  200.                 sState.oImage->SetProperty, DATA=*sState.pImageTemp
  201.             if (sEvent.value EQ 1 AND twin EQ 0) then $
  202.                 sState.oImage->SetProperty, DATA=*sState.pImageTopoTemp
  203.             if (sEvent.value EQ 1 AND twin EQ 1) then $
  204.                 sState.oImage->SetProperty, DATA=*sState.pImageTopo
  205.             if (sEvent.value EQ 0 AND twin EQ 1) then $
  206.                 sState.oImage->SetProperty, DATA=*sState.pImageTempTopo
  207.             sState.oWindow->Draw, sState.oView
  208.             WIDGET_CONTROL, HOURGLASS=0
  209.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  210.         end
  211.  
  212.         ;  Reset perspective.
  213.         ;
  214.         'RESET': begin
  215.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  216.             sState.oModelRotate->SetProperty, $
  217.                 TRANSFORM=sState.resetTransform
  218.             sState.oWindow->Draw, sState.oView
  219.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  220.         end
  221.  
  222.         ;  Handle radio button events.
  223.         ;  Here Handle event for showing over oceans.
  224.         ;
  225.         'RADIO2': begin
  226.             WIDGET_CONTROL, HOURGLASS=1
  227.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  228.             WIDGET_CONTROL, sState.wGroup1, GET_VALUE=twin
  229.             if (sEvent.value EQ 0 AND twin EQ 0) then $
  230.                 sState.oImage->SetProperty, DATA=*sState.pImageTemp
  231.             if (sEvent.value EQ 1 AND twin EQ 0) then $
  232.                 sState.oImage->SetProperty, DATA=*sState.pImageTempTopo
  233.             if (sEvent.value EQ 1 AND twin EQ 1) then $
  234.                 sState.oImage->SetProperty, DATA=*sState.pImageTopo
  235.             if (sEvent.value EQ 0 AND twin EQ 1) then $
  236.                 sState.oImage->SetProperty, DATA=*sState.pImageTopoTemp
  237.             sState.oWindow->Draw, sState.oView
  238.             WIDGET_CONTROL, HOURGLASS=0
  239.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  240.         end
  241.  
  242.         ;  Handle trackball events here.
  243.         ;  still need to add trackball object 
  244.         ;  and place in object hierarchy.
  245.         ;
  246.         'DRAW': begin
  247.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  248.             bHaveTransform=sState.oTrack->Update(sEvent, TRANSFORM=qmat)
  249.             if (bHaveTransform NE 0) then begin
  250.               sState.oModelRotate->GetProperty, TRANSFORM=trans
  251.               mtrans=trans # qmat
  252.               sState.oModelRotate->SetProperty, TRANSFORM=mtrans
  253.             endif
  254.  
  255.             ;  Handle button press.
  256.             ;
  257.             if (sEvent.type EQ 0) then $    
  258.                 WIDGET_CONTROL, sState.wDraw, DRAW_MOTION=1
  259.             if (sEvent.type EQ 2) then begin
  260.                 if (bHaveTransform) then begin
  261.                     sState.oWindow->SetProperty, QUALITY=0
  262.                     sState.oWindow->Draw,sState.oView
  263.                 endif
  264.             endif
  265.  
  266.             ;  Handle button release.
  267.             ;
  268.             if (sEvent.type EQ 1) then begin     
  269.                 sState.oWindow->SetProperty, QUALITY=2
  270.                 WIDGET_CONTROL, sState.wDraw, DRAW_MOTION=0
  271.                 sState.oWindow->Draw, sState.oView
  272.             endif
  273.  
  274.             ;  Handle expose events.
  275.             ;
  276.             if (sEvent.type EQ 4) then begin
  277.                 sState.oWindow->Draw, sState.oView
  278.             endif
  279.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  280.         end
  281.  
  282.         ;  Quit this application.
  283.         ;
  284.         'QUIT': begin
  285.             WIDGET_CONTROL, sEvent.top, /DESTROY
  286.         end
  287.  
  288.         ; Display the information file.
  289.         ;
  290.         'ABOUT' : begin
  291.             if (XREGISTERED('XDisplayFile') NE 0) then RETURN
  292.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  293.             XDISPLAYFILE, sState.fileNameAbout, $
  294.                 WIDTH=55, HEIGHT=14, DONE_BUTTON='Done', $
  295.                 TITLE='About the Globe Demo' , $
  296.                 GROUP=sEvent.top
  297.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  298.         end
  299.  
  300.         ;  Handle all other events.
  301.         ;
  302.     ELSE:    ;  Do nothing
  303.  
  304.     endcase
  305.  
  306. end
  307.  
  308. ;----------------------------------------------------------------------
  309. ;
  310. ; PURPOSE  Cleanup everything associated with the
  311. ;          Globe demo, including all objects and pointers.
  312. ;          Restore the original color table.
  313. ;
  314. pro d_GlobeCleanup, tlb
  315.  
  316.     WIDGET_CONTROL, tlb, GET_UVALUE=sState, /NO_COPY
  317.  
  318.     ;  Restore the previous color table.
  319.     ;
  320.     TVLCT, sState.colorTable
  321.  
  322.     ;  Destroy the top objects & attribute objects.
  323.     ;
  324.     OBJ_DESTROY, sState.oView
  325.     OBJ_DESTROY, sState.oPalette
  326.     OBJ_DESTROY, sState.oTrack
  327.     OBJ_DESTROY, sState.oText
  328.     OBJ_DESTROY, sState.oFont
  329.     OBJ_DESTROY, sState.oContainer
  330.  
  331.     ;  Free all pointers.
  332.     ;
  333.     PTR_FREE, sState.pImageTempTopo
  334.     PTR_FREE, sState.pImageTopoTemp
  335.     PTR_FREE, sState.pImageTemp
  336.     PTR_FREE, sState.pImageTopo
  337.  
  338.     ;  Map the group leader base if it exists.
  339.     ;
  340.     if (WIDGET_INFO(sState.groupBase, /VALID_ID)) then $
  341.         WIDGET_CONTROL, sState.groupBase, /MAP
  342.  
  343. end
  344.  
  345. ;----------------------------------------------------------------------
  346. ;
  347. ; PURPOSE  Inputs the images used in the Globe demo.
  348. ;          This procedure returns
  349. ;          four pointers back to the caller.
  350. ;          These pointers point to the given images.
  351. ;
  352. pro GlobeReadImages, $
  353.     fileNameElev, $     ;IN: filename for elevation dataset
  354.     fileNameTemp, $     ;IN: filename for temperature dataset
  355.     nColors, $          ;IN: number of colors used to scale both images
  356.     pImageTemp, $       ;OUT: world temperatures
  357.     pImageTopo, $       ;OUT: world topography
  358.     pImageTempTopo, $   ;OUT: continental temperature and oceanic elevation
  359.     pImageTopoTemp, $   ;OUT: ocean temperature and continental elevation
  360.     reds, $             ;OUT: red color indices
  361.     greens, $           ;OUT: green color indices
  362.     blues               ;OUT: blue color indices
  363.  
  364.     ;  Innput DEM from IDL distribution ("worldelv.dat") and
  365.     ;  corresponding temperature dataset from
  366.     ;  a .SAV file ("worldtmp.sav").
  367.     ;
  368.     OPENR, lun, fileNameElev, /GET_LUN
  369.     topo=BYTARR(360, 360)
  370.     READU, lun, topo
  371.     CLOSE, LUN
  372.     FREE_LUN, lun
  373.     temps=BYTARR(360, 360)
  374.  
  375.     ;  Read  the temperature image. 
  376.     ;
  377.     Read_Gif, fileNameTemp, Temps, Reds, Greens, Blues
  378.  
  379.     ;  Build masks to divide the two datasets.
  380.     ;
  381.     oceanMask=WHERE(topo lt 124)
  382.     landMask=WHERE(topo ge 124)
  383.  
  384.     ;  Create DEM( Digital elevation Model) images.
  385.     ;  (Color Ranges: [0]-[nColors/2-1]).
  386.     ;
  387.     topoOceanScaled=BYTSCL(topo, TOP=nColors/2-1, $
  388.         MIN=MIN(topo[oceanMask]), MAX=MAX(topo[oceanMask]))
  389.     topoLandScaled=BYTSCL(topo, TOP=nColors/2-1, $
  390.         MIN=MIN(topo[landMask]), MAX=MAX(topo[landMask]))
  391.     topoScaled=BYTSCL(topo, TOP=nColors/2-1)
  392.  
  393.     ;  Create temperature images. 
  394.     ;  (Color Ranges: [nColors/2]-[nColors-1]).
  395.     ;
  396.     tempLandScaled=BYTSCL(temps, TOP=nColors/2-1, $
  397.         MIN=MIN(temps[landMask]), $
  398.         MAX=MAX(temps[landMask]))+BYTE(nColors/2)
  399.     tempOceanScaled=BYTSCL(temps, TOP=nColors/2-1, $
  400.         MIN=MIN(temps[oceanMask]), $
  401.         MAX=MAX(temps[oceanMask]))+BYTE(nColors/2)
  402.     tempScaled=BYTSCL(temps, TOP=nColors/2-1)+BYTE(nColors/2)
  403.  
  404.     ;  Create pointers to two images that are created based on the
  405.     ;  respective topography and temperature scalings.
  406.     ;
  407.     pImageTemp=PTR_NEW(tempScaled)
  408.     pImageTopo=PTR_NEW(topoScaled)
  409.     imageTempTopo=BYTARR(360, 360)    ;temperatures over continents
  410.     imageTempTopo[landMask]=tempLandScaled[landMask]
  411.     imageTempTopo[oceanMask]=topoOceanScaled[oceanMask]
  412.     pImageTempTopo=PTR_NEW(imageTempTopo)
  413.     imageTopoTemp=BYTARR(360, 360)    ;temperatures over oceans
  414.     imageTopoTemp[oceanMask]=tempOceanScaled[oceanMask]
  415.     imageTopoTemp[landMask]=topoLandScaled[landMask]
  416.     pImageTopoTemp=PTR_NEW(imageTopoTemp)
  417.  
  418.     ;  Scale color vectors based on number of colors.
  419.     ;
  420.     reds=CONGRID(reds, nColors)
  421.     greens=CONGRID(greens, nColors)
  422.     blues=CONGRID(blues, nColors)
  423.  
  424. end
  425.  
  426. ;----------------------------------------------------------------------
  427. ;
  428. ; PURPOSE  Creates the object hierarchy
  429. ;
  430. function GlobeMakeObjects, $
  431.     reds, $                ;IN: red color lookups
  432.     greens, $                           ;IN: green color lookups
  433.     blues, $                            ;IN: blue color lookups
  434.     screenSize, $                       ;IN: screensize dimensions
  435.     pImageTempTopo, $                   ;IN: pointer to image
  436.     oWindow                             ;IN: window object
  437.  
  438.     myView = [-1.0, -1.0, 2.0, 2.0]
  439.     ;  Create view object.
  440.     ;
  441.     oView = OBJ_NEW('IDLgrView', PROJECTION=2, EYE=4.0, $
  442.         COLOR=[0,0,0], $
  443.         VIEW=[-1.0, -1.0, 2.0, 2.0], ZCLIP=[1.0, -1.0])
  444.  
  445.     ;  Make the starting up text location centered.
  446.     ;
  447.     textLocation = [myview[0]+0.5*myview[2], myview[1]+0.5*myview[3]]
  448.  
  449.     ;  Create and display the PLEASE WAIT text.
  450.     ;
  451.     oFont = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=20)
  452.     oText = OBJ_NEW('IDLgrText', $
  453.         'Starting up  Please wait...', $
  454.         ALIGN=0.5, $
  455.         LOCATION=textLocation, $
  456.         COLOR=[255,255,0], FONT=oFont)
  457.  
  458.  
  459.     ;  Create model objects for translation, rotation, and scaling.
  460.     ;
  461.     oModelTranslate=OBJ_NEW('IDLgrModel')
  462.     oModelRotate=OBJ_NEW('IDLgrModel')
  463.     oModelScale=OBJ_NEW('IDLgrModel')
  464.     oModelTranslate->Add, oModelRotate
  465.     oModelRotate->Add, oModelScale
  466.  
  467.     ;  Show the starting up text.
  468.     ;
  469.     oview->Add, oModelTranslate
  470.     oModelTranslate->Add, oText
  471.     owindow->Draw, oView
  472.  
  473.     ;  Create color palette object.
  474.     ;
  475.     oPalette=obj_new('IDLgrPalette', reds, greens, blues)
  476.  
  477.     ;  Create trackball object.
  478.     ;
  479.     oTrack=OBJ_NEW('trackball', $
  480.         [(screenSize[0]*.4)/2.0, (screenSize[0]*.4)/2.0], $
  481.         (screenSize[0]*.4)/2.0)
  482.  
  483.     ;  Create image object and add to model hierarchy.
  484.     ;
  485.     oImage=OBJ_NEW('IDLgrImage', *pImageTempTopo, HIDE=1, $
  486.         PALETTE=oPalette)
  487.     oModelRotate->Add, oImage
  488.  
  489.     ;  Create orb object and add to model hierarchy.
  490.     ;
  491.     oSphere=OBJ_NEW('orb', DENSITY=0.99, /TEX_COORDS, $
  492.         TEXTURE_MAP=oImage, COLOR=[255, 255, 255], RADIUS=0.90)
  493.     oModelRotate->Add, oSphere
  494.  
  495.     ;  Add model hierarchy to view, rotate or whatever,
  496.     ;  draw view to window.
  497.     ;
  498.     oModelRotate->Rotate, [1, 0, 0], -90
  499.  
  500.     oModelRotate->GetProperty, TRANSFORM=resetTransform
  501.  
  502.     oContainer = OBJ_NEW('IDLgrContainer')
  503.     oContainer->Add, oView
  504.     oContainer->Add, oTrack
  505.  
  506.     RETURN, {oView:oView, $
  507.         oModelTranslate: oModelTranslate, $
  508.         oModelRotate: oModelRotate, $
  509.         oModelScale: oModelScale, $
  510.         oPalette: oPalette, $
  511.         oImage: oImage, $
  512.         oSphere: oSphere, $
  513.         oTrack: oTrack, $
  514.         oWindow: oWindow, $
  515.         oContainer: oContainer, $
  516.         OText: oText, $
  517.         OFont: oFont, $
  518.         resetTransform:resetTransform}
  519.  
  520. end
  521.  
  522. ;----------------------------------------------------------------------
  523. ;
  524. ; PURPOSE  This is the main widget definition
  525. ;          routine used in the Globe demo.
  526. ;          It constructs a widget and object
  527. ;          hierarchy which can be used to 
  528. ;          manipulate some images.
  529. ;
  530. pro D_Globe, $
  531.     GROUP=group, $        ;IN: (opt) group identifier
  532.     APPTLB=apptlb        ;OUT: (opt) TLB of this application
  533.  
  534.     ;  Check the validity of the group identifier.
  535.     ;
  536.     ngroup=N_ELEMENTS(group)
  537.     if (ngroup NE 0) then begin
  538.         check=WIDGET_INFO(group, /VALID_ID)
  539.         if (check NE 1) then begin
  540.             print,'Error, the group identifier is not valid'
  541.             print, 'Return to the main application'
  542.             RETURN
  543.         endif
  544.         groupBase = group
  545.     endif else groupBase = 0L
  546.  
  547.     ;  Get the current color table. 
  548.     ;  It will be restored when exiting.
  549.     ;
  550.     TVLCT, savedR, savedG, savedB, /GET
  551.     colorTable=[[savedR],[savedG],[savedB]]
  552.  
  553.     ;  Get the screen size.
  554.     ;
  555.     DEVICE, GET_SCREEN_SIZE = screenSize
  556.  
  557.     ;  Declare filenames used with the globe demo.
  558.     ;
  559.     fileNameElev=FILEPATH('worldelv.dat', $
  560.         SUBDIR=['examples','data'])
  561.     fileNameTemp=FILEPATH('worldtmp.gif', $
  562.         SUBDIR=['examples','demo','demodata'])
  563.     fileNameTips=FILEPATH('globe.tip', $
  564.         SUBDIR=['examples','demo','demotext'])
  565.     fileNameAbout=FILEPATH('globe.txt', $
  566.         SUBDIR=['examples','demo','demotext'])
  567.  
  568.     ;  Get the tips.
  569.     ;
  570.     sText=getTips(fileNameTips)
  571.     nWidgets=2
  572.     wText=LONARR(nWidgets)
  573.  
  574.     ;  Read image datasets.  GlobeReadImages returns two pointers to the 
  575.     ;  respective images.  Each image contains two datasets, whereby
  576.     ;  each dataset is scaled using half of the colors specified
  577.     ;  in calling GlobeReadImages.
  578.     ;
  579.     nColors=190
  580.     GlobeReadImages, fileNameElev, fileNameTemp, nColors, $
  581.         pImageTemp, pImageTopo, pImageTempTopo, pImageTopoTemp, $
  582.         reds, greens, blues
  583.  
  584.     ;  Construct all base widgets.
  585.     ;
  586.     if (N_ELEMENTS(group) EQ 0) then begin
  587.         wTopBase=WIDGET_BASE(TITLE='Globe Demo', $
  588.             XPAD=0, YPAD=0, $
  589.             /TLB_KILL_REQUEST_EVENTS, $
  590.             /COLUMN, TLB_FRAME_ATTR=1, MBAR=barBase)
  591.     endif else begin
  592.         wTopBase=WIDGET_BASE(TITLE='Globe Demo', $
  593.             XPAD=0, YPAD=0, $
  594.             /TLB_KILL_REQUEST_EVENTS, $
  595.             GROUP_LEADER=group, $
  596.             /COLUMN, TLB_FRAME_ATTR=1, MBAR=barBase)
  597.     endelse
  598.  
  599.         ;  Create the buttons in the menu bar.
  600.         ;
  601.         wFileButton=WIDGET_BUTTON(barBase, VALUE='File')
  602.  
  603.             wQuitButton=WIDGET_BUTTON(wFileButton, VALUE='Quit', $
  604.                 UVALUE='QUIT')
  605.  
  606.         wOptionButton=WIDGET_BUTTON(barBase, VALUE='Options')
  607.  
  608.             wResetButton=WIDGET_BUTTON(wOptionButton, $
  609.                 VALUE='Reset Orientation', UVALUE='RESET')
  610.   
  611.         wHelpButton=WIDGET_BUTTON(barBase, VALUE='About', /HELP)
  612.  
  613.             wAboutButton=WIDGET_BUTTON(wHelpButton, UVALUE='ABOUT', $
  614.                 VALUE='About the Globe Demo')
  615.  
  616.         ;  Create the widgets other than the menu bar.
  617.         ;
  618.         wSubBase=WIDGET_BASE(wTopBase, COLUMN=2)
  619.  
  620.             wLeftBase=WIDGET_BASE(wSubBase, /ALIGN_CENTER, /COLUMN)
  621.  
  622.                 wLeftBaseSub1=WIDGET_BASE(wLeftBase, $
  623.                     /ALIGN_CENTER, /COLUMN, /FRAME)
  624.  
  625.                     wSelect1=WIDGET_LABEL(wLeftBaseSub1, $
  626.                         VALUE='Display Over Continents:')
  627.  
  628.                     radioOptions=['Temperature', 'Topography']
  629.  
  630.                     wGroup1=CW_BGROUP(wLeftBaseSub1, $
  631.                         radioOptions, SET_VALUE=1, $
  632.                         /ROW, /RETURN_INDEX, /EXCLUSIVE, $
  633.                         /NO_RELEASE, UVALUE='RADIO1')
  634.  
  635.                 wLeftBaseSub2=WIDGET_BASE(wLeftBase, $
  636.                     /ALIGN_CENTER, /COLUMN, /FRAME)
  637.  
  638.                     wSelect2=WIDGET_LABEL(wLeftBaseSub2, $
  639.                         VALUE='Display Over Oceans:')
  640.  
  641.                     wGroup2=CW_BGROUP(wLeftBaseSub2, $
  642.                         radioOptions, SET_VALUE=0, $
  643.                         /ROW, /RETURN_INDEX, /EXCLUSIVE, $
  644.                         /NO_RELEASE, UVALUE='RADIO2')
  645.  
  646.                 wLeftBaseSub3=WIDGET_BASE(wLeftBase, $
  647.                     /ALIGN_CENTER, /COLUMN, /FRAME)
  648.  
  649.                     wslider3=WIDGET_SLIDER(wLeftBaseSub3, $
  650.                         /SUPPRESS, MINIMUM=nColors/2, $
  651.                         MAXIMUM=nColors-1, $
  652.                         VALUE=nColors/2, $
  653.                         EVENT_PRO='GlobeStretch_Event', $
  654.                         TITLE='Stretch temperature minimum')
  655.  
  656.                     wslider4=WIDGET_SLIDER(wLeftBaseSub3, $
  657.                         /SUPPRESS, MINIMUM=nColors/2, $
  658.                         MAXIMUM=nColors-1, $
  659.                         VALUE=nColors-1, $
  660.                         EVENT_PRO='GlobeStretch_Event', $
  661.                         TITLE='Stretch temperature maximum')
  662.  
  663.                 wLeftBaseSub4=WIDGET_BASE(wLeftBase, $
  664.                     /ALIGN_CENTER, /COLUMN, /FRAME)
  665.  
  666.                     wslider1=WIDGET_SLIDER(wLeftBaseSub4, $
  667.                         /SUPPRESS, MINIMUM=0, $
  668.                         MAXIMUM=nColors/2-1, VALUE=0, $
  669.                         EVENT_PRO='GlobeStretch_Event', $
  670.                         TITLE='Stretch topography minimum ')
  671.  
  672.                     wslider2=WIDGET_SLIDER(wLeftBaseSub4, $
  673.                         /SUPPRESS, MINIMUM=0, $
  674.                         MAXIMUM=nColors/2-1, VALUE=nColors/2-1, $
  675.                         EVENT_PRO='GlobeStretch_Event', $
  676.                         TITLE='Stretch topography maximum ')
  677.  
  678.             wRightBase=WIDGET_BASE(wSubBase, /ALIGN_CENTER, /COLUMN)
  679.  
  680.                 wDraw=WIDGET_DRAW(wRightBase, XSIZE=screenSize[0]*.48, $
  681.                     YSIZE=ScreenSize[0]*.48, $  ;keep isotropic
  682.                     UVALUE='DRAW', /BUTTON_EVENTS, $
  683.                     GRAPHICS_LEVEL=2, RETAIN=0, /EXPOSE_EVENTS)
  684.  
  685.         wStatusBase=WIDGET_BASE(wTopBase, /ROW, MAP=0)
  686.  
  687.             nWidgets=2
  688.             wText=LONARR(nWidgets)
  689.             widTips, wStatusBase, sText.text, wText, NWIDGETS=nWidgets
  690.  
  691.     ;  Realize  the widget hierarchy.
  692.     ;
  693.     WIDGET_CONTROL, wTopBase, /REALIZE
  694.     WIDGET_CONTROL, HOURGLASS=1
  695.     WIDGET_CONTROL, wDraw, GET_VALUE=oWindow
  696.  
  697.     ;  Set the user values of each slider to the ids of all sliders because
  698.     ;  these will be needed in the event handler to avoid cases whereby 
  699.     ;  minimum sliders are set to values larger than maximum sliders and
  700.     ;  vice versa.
  701.     ;
  702.     wsliders=[wslider1, wslider2, wslider3, wslider4]
  703.  
  704.     ;  Set the initial value of the sliders.
  705.     ;
  706.     WIDGET_CONTROL, wslider1, SET_UVALUE=wsliders
  707.     WIDGET_CONTROL, wslider2, SET_UVALUE=wsliders
  708.     WIDGET_CONTROL, wslider3, SET_UVALUE=wsliders
  709.     WIDGET_CONTROL, wslider4, SET_UVALUE=wsliders
  710.  
  711.     ;  Size and map the tips.
  712.     ;
  713.     sizeTips, wTopBase, wText, wStatusBase
  714.     WIDGET_CONTROL, wStatusBase, MAP=1
  715.  
  716.     ;  Create the objects.
  717.     ;  Make the continent-topo  & ocean-temperature 
  718.     ;  the default view.
  719.     ;
  720.     sObject=GlobeMakeObjects(reds, greens, blues, screenSize, $
  721.         pImageTopoTemp, oWindow)
  722.  
  723.     ;  Build sState structure used in event handlers.
  724.     ;
  725.     sState={$
  726.         wGroup1:wGroup1, $                          ; Widget Id radio buttons
  727.         wGroup2:wGroup2, $                          ; Widget Id radio buttons
  728.         wDraw:wDraw, $                              ; Widget draw ID
  729.         oImage:sObject.oImage, $                    ; Image object
  730.         oSphere:sObject.oSphere, $                  ; Sphere object
  731.         oTrack:sObject.oTrack, $                    ; Trackball object
  732.         oModelTranslate:sObject.oModelTranslate, $  ; Models
  733.         oModelRotate:sObject.oModelRotate, $
  734.         oModelScale:sObject.oModelScale, $
  735.         OContainer: sObject.oContainer, $           ; Container object
  736.         oWindow:sObject.oWindow, $                  ; Widnow object
  737.         oView:sObject.oView, $                      ; View object
  738.         oFont:sObject.oFont, $                      ; Font object
  739.         oText:sObject.oText, $                      ; Text object
  740.         oPalette:sObject.oPalette, $                ; Color palette object
  741.         resetTransform:sObject.resetTransform, $    ; Transformation matrix to reset
  742.         pImageTemp:pImageTemp, $                    ; Pointers to images
  743.         pImageTopo:pImageTopo, $
  744.         pImageTempTopo:pImageTempTopo, $
  745.         pImageTopoTemp:pImageTopoTemp, $
  746.         nColors:nColors, $                          ; Number of available colors
  747.         reds:reds, $                                ; RGB color arrays
  748.         greens:greens, $
  749.         blues:blues, $
  750.         colorTable:colorTable, $                    ; Color table to restore
  751.         fileNameAbout:fileNameAbout,  $
  752.         groupBase: groupBase $                      ; Base of Group Leader
  753.     }
  754.  
  755.     WIDGET_CONTROL, wTopBase, SET_UVALUE=sState, /NO_COPY
  756.  
  757.     WIDGET_CONTROL, HOURGLASS=0
  758.  
  759.     ;  Remove the starting up text.
  760.     ;
  761.     sObject.oModelTranslate->Remove, sObject.oText
  762.  
  763.     ;  Returns the top level base to the APPTLB keyword.
  764.     ;
  765.     appTLB=wTopBase
  766.  
  767.     ;  Modify the initial setting of the sliders. First create
  768.     ;  a pseudo event structure, then call the globeStretch_Event
  769.     ;  routine with the pseudo structure, then set the slider
  770.     ;  to the desired value
  771.     ;
  772.     ;  Stretching the temperature minimum slider at 30% of
  773.     ;  its range and rotate the globe.
  774.     ;
  775.     sObject.oModelRotate->Rotate, [0, 1, 0], -20.0
  776.     sObject.oModelRotate->Rotate, [1, 0, 0], 10.0
  777.     deltaTempMin = (nColors-1 - nColors/2 ) * 0.3
  778.     increment = (deltaTempMin) / 2
  779.     for i = 0, deltaTempMin, increment do begin
  780.         sObject.oModelRotate->Rotate, [0, 1, 0], -5
  781.         sObject.oModelRotate->Rotate, [1, 0, 0], 2.5
  782.          newValue = nColors/2 + i
  783.          pseudoEvent = { $
  784.              ID : wslider3, $ 
  785.              TOP: wTopBase, $
  786.              HANDLER: wslider3, $
  787.              VALUE: newValue, $
  788.              DRAG: 0 $
  789.          }
  790.          WIDGET_CONTROL, wslider3, SET_VALUE=newValue
  791.          globeStretch_Event, pseudoEvent
  792.     endfor
  793.  
  794.     ;  Stretching the temperature maximum slider at 85% of
  795.     ;  its range and rotate the globe.
  796.     ;
  797.     deltaTempMax = (nColors-1 - nColors/2)*0.15
  798.  
  799.     increment = (deltaTempMax) / 3
  800.     for i = 0, deltaTempMax, increment do begin
  801.         sObject.oModelRotate->Rotate, [0, 1, 0], -5
  802.         sObject.oModelRotate->Rotate, [1, 0, 0], 2.5
  803.         newValue = (nColors-1) - i
  804.         pseudoEvent = { $
  805.             ID : wslider4, $ 
  806.             TOP: wTopBase, $
  807.             HANDLER: wslider4, $
  808.             VALUE: newValue, $
  809.             DRAG: 0 $
  810.         }
  811.         WIDGET_CONTROL, wslider4, SET_VALUE=newValue
  812.         globeStretch_Event, pseudoEvent
  813.     endfor
  814.  
  815.     ;  Stretching the topography maximum slider at 35% of
  816.     ;  its range.
  817.     ;
  818.     deltaTempMax = nColors/2 - 1
  819.     newValue = (nColors/2 - 1) * 0.35
  820.     pseudoEvent = { $
  821.         ID : wslider2, $ 
  822.         TOP: wTopBase, $
  823.         HANDLER: wslider2, $
  824.         VALUE: newValue, $
  825.         DRAG: 0 $
  826.     }
  827.     WIDGET_CONTROL, wslider2, SET_VALUE=newValue
  828.     globeStretch_Event, pseudoEvent
  829.  
  830.     ;  Register with the XMANAGER
  831.     ;
  832.     XMANAGER, 'd_Globe', wTopBase, /NO_BLOCK, $
  833.         EVENT_HANDLER='d_Globe_Event', CLEANUP="d_GlobeCleanup"
  834.  
  835. end
  836.  
  837.